/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ceair.flight.refund.service.notification.impl;

import com.ceair.flight.refund.dto.appmoblie.RefundApplyDto;
import com.ceair.flight.refund.dto.appmoblie.RefundTktDto;
import com.ceair.flight.refund.dto.uatp.QueryCardForRefundNo;
import com.ceair.flight.refund.location.dt.enums.RefundStatusEnum;
import com.ceair.flight.refund.location.service.IRefundLocationService;
import com.ceair.flight.refund.service.notification.IUatpRefundNotification;
import com.ceair.flight.refund.util.Base64Util;
import com.ceair.flight.refund.util.GsonUtil;
import com.ceair.muservice.basicdata.dto.channel.ChannelManageDto;
import com.ceair.muservice.common.dto.queue.MailAndSMSMessage;
import com.ceair.muservice.common.enums.message.TemplateNameEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author Colin_You
 */
@Service("uatpRefundNotification")
public class UatpRefundNotification extends AbstractNotification implements IUatpRefundNotification {

    private static final Logger LOG = LoggerFactory.getLogger(UatpRefundNotification.class);
    private static final String PARAM_VALUE = "PARAM_VALUE";
    private static final String PAYMENT_CHANNEL_CODE_UATP = "UATP";
    @Autowired
    private IRefundLocationService refundLocationService;

    TemplateNameEnum getTemplateName(Map args) {
        if (args.containsKey(MOBILES)) {
            return TemplateNameEnum.UATP_NOTIFY_EMS;
        }
        return TemplateNameEnum.UATP_NOTIFY_MAIL;
    }

    @Override
    public boolean sendNotification(RefundApplyDto refundApply) {
        if (!isValidForSend(refundApply)) {
            LOG.warn("Refund apply {} not valid for sending UATP notifications", refundApply.getId());
            return false;
        }
        boolean isMailSuccess = false;
        boolean isSmsSuccess = false;
        Map args = buildCommonArgs(refundApply);
        try {
            sendMail(new HashMap(args), refundApply);
            isMailSuccess = true;
            LOG.debug("Send UATP email message successfully");
        } catch (Exception ex) {
            LOG.error("Send UATP mail message failed", ex);
        }
        try {
            sendSms(new HashMap(args), refundApply);
            isSmsSuccess = true;
            LOG.debug("Send UATP sms message successfully");
        } catch (Exception ex) {
            LOG.error("Send UATP sms message failed", ex);
        }
        return isMailSuccess || isSmsSuccess;
    }

    @Override
    public void notify(final Map args) {
        MailAndSMSMessage message = buildMessage(args);
        if (message != null) {
            String messageEntity = GsonUtil.toJson(message);
            LOG.debug("UATP notification message entity: {}", messageEntity);
            getMessageSender().sendMessage(message);
        } else {
            throw new IllegalStateException("Send failed");
        }
    }

    private boolean isValidForSend(RefundApplyDto refundApply) {
        String status = refundApply.getStatus();
        String paymentChannelCode = refundApply.getRefundTkt().getPaymentChannelCode();
        RefundStatusEnum statusEnum = RefundStatusEnum.getByCode(status);
        return (RefundStatusEnum.WAITING_CARD_FOR_REFUND_NO == statusEnum
                || RefundStatusEnum.SECOND_AUDIT_PASS == statusEnum)
                && paymentChannelCode.contains(PAYMENT_CHANNEL_CODE_UATP);
    }

    private Map buildCommonArgs(RefundApplyDto refundApply) {
        String encryptedStr = getEncryptInfo(refundApply);
        Map args = new HashMap(2, 1.0f);
        args.put(PARAM_VALUE, encryptedStr);
        RefundTktDto refundTkt = refundApply.getRefundTkt();
        String channelNo = refundTkt.getChannelNo();
        //TODO 20190408修改
        ChannelManageDto channelManageDto = refundLocationService.findChannelByCode(channelNo);
        String site = channelManageDto.getLanguageCode();
        String[] siteSplit = site.split("_");
        String language = siteSplit[0];
        String country = siteSplit[siteSplit.length - 1];
        args.put(SITE, language);
        args.put(LANGUAGE, language);
        args.put(COUNTRY, country);
        args.put(CHANNEL, channelNo);
        return args;
    }

    private void sendSms(Map args, RefundApplyDto refundApply) {
        String phone = getPhoneNumber(refundApply);
        if (phone == null || phone.isEmpty()) {
            LOG.error("No available phone for UATP notification");
            throw new IllegalStateException("No available phone for UATP notification, stopping sending sms notificaton");
        }

        args.put(MOBILES, phone);
        args.put(IS_INTER, isDomesticPhoneNo(phone) ? "0" : "1");
        this.notify(args);
    }

    private void sendMail(Map args, RefundApplyDto refundApply) {
        String mailAddress = getMailAddress(refundApply);
        if (mailAddress == null || mailAddress.isEmpty()) {
            LOG.error("No available email address for UATP notification");
            throw new IllegalStateException("No available email address for UATP notification, stopping sending email notificaton");
        }

        args.put(RECEIVER, mailAddress);
        this.notify(args);
    }

    boolean isDomesticPhoneNo(String phone) {
        return phone.startsWith("86") || phone.startsWith("+86") || phone.length() == 11;
    }

    private String getEncryptInfo(RefundApplyDto refundApply) {
        RefundTktDto refundTkt = refundApply.getRefundTkt();

        QueryCardForRefundNo info = new QueryCardForRefundNo();
        info.setTimestamp(System.currentTimeMillis());

        String flightOrderNo = refundTkt.getFlightOrderNo();
        info.setFlightOrderNo(flightOrderNo);

        info.setTicketNo(refundTkt.getTicketNo());
        String source = GsonUtil.toJson(info);
        return Base64Util.encode(source);
    }

    /**
     * 获取通知邮件信息,订单中填的联系邮箱优先,然后才是乘客信息中的邮箱信息
     *
     * @param refundApply
     * @return
     */
    private String getMailAddress(RefundApplyDto refundApply) {
        String email = refundApply.getContactEmail();
        if (email != null && !email.isEmpty()) {
            return email;
        }
        RefundTktDto refundTkt = refundApply.getRefundTkt();
        return refundTkt.getPaxEmail();
    }

    /**
     * 获取通知电话信息,订单中填的联系电话优先,然后才是乘客信息中的电话信息
     *
     * @param refundApply
     * @return
     */
    private String getPhoneNumber(RefundApplyDto refundApply) {
        String phone = refundApply.getContactPhone();
        if (phone != null && !phone.isEmpty()) {
            return phone;
        }
        RefundTktDto refundTkt = refundApply.getRefundTkt();
        return refundTkt.getPaxPhone();
    }

}
